home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
pcmagazi
/
1989
/
18
/
menu.asm
< prev
next >
Wrap
Assembly Source File
|
1989-08-12
|
135KB
|
3,133 lines
PAGE 66,132 ;
NAME MENU ;
TITLE Menu utility ;
;
; MENU provides a screen oriented interface for use in constructing batch files
; using menu selection and fill-in-the-blanks approaches.
;
; Use:
;
; MENU [/N/D/E] [screen] [template] [out out out ...]
;
; "screen" is the display file that the user sees. "screen" contains the text
; to be displayed, the display attributes, and display management commands.
; The logical screen may be longer than a physical screen.
;
; "template" is a file that defines the format of the output file "out".
; "template" consists of the exact text to be sent to "out" except for the
; inclusion of bracketed references. Text of the form [nnn] is replaced by
;
; "out" is the name of the file to receive the final output. Multiple out
; files may be specified.
;
; Copyright (c) 1989 Ziff Communications Co.
; Written May 1989 for PC Magazine by Ronald Q. Smith
;
; Constant definitions.
;
; DOS Interface
;
DOS$ EQU 21H ; DOS function call INT
; Function values for DOS$
DATE$ EQU 2AH ; Get date
TIME$ EQU 2CH ; Get time of day
CREATE$ EQU 3CH ; Create file
OPEN$ EQU 3DH ; Open file
CLOSE$ EQU 3EH ; Close file
RDFILE$ EQU 3FH ; Read file
WRFILE$ EQU 40H ; Write file
EXIT$ EQU 4CH ; Return to DOS
STDIN EQU 0 ; Standard input handle
STDOUT EQU 1 ; Standard output handle
ERROUT EQU 2 ; Handle for error messages
;
; BIOS Interface
;
VIDEO$ EQU 10H ; CRT handler INT
; Function values for VIDEO$
SMODE$ EQU 0 ; Set video mode
CRS$ EQU 2 ; Set cursor position function
RDCRS$ EQU 3 ; Read cursor position function
PAGE$ EQU 5 ; Set video page
RACH$ EQU 8 ; Read attribute and character
WACH$ EQU 9 ; Write attribute and character
WCHR$ EQU 10 ; Write character
VIDSTAT$ EQU 15 ; Get current video state
EGASTAT$ EQU 17 ; Get EGA status
ALTSEL$ EQU 18 ; Alternate select to EGA
;
KYBD$ EQU 16H ; Keyboard handler INT
;
; Non-printing ASCII characters
;
BS_CHR EQU 8 ; Back space
TAB_CHR EQU 9 ; Tab
LF_CHR EQU 10 ; Line feed
CR_CHR EQU 13 ; Carriage return
EOF_CHR EQU 26 ; End-of-file sentinel character
ESC_CHR EQU 27 ; Esc
;
; Screen constants.
;
SCR_ATTR EQU 7 ; White on black default
MONO_SEG EQU 0B000H ; Monochrome adapter refresh segment
COLOR_SEG EQU 0B800H ; Color/EGA adapter refresh segment
;
; I/O constants.
;
L_INB EQU 512 ; Input buffer size
L_OUTB EQU 512 ; Output buffer size
EDIT_FLD EQU 100 ; Maximum number of input fields
;
; BIOS Data segment
;
BIOS_DATA SEGMENT AT 40H ;
ORG 63H ;
ADDR_6845 DW ? ; I/O address of current display
ORG 87H ;
EGA_INFO DB ? ; EGA status byte
EGA_MASK EQU 00001000B ; EGA active bit (0=active)
BIOS_DATA ENDS ;
;
; Macros.
;
; DBA creates character,attribute pairs from an attribute value (ATTR) and
; a string (STR). This macro may be used to create values to be copied
; directly to the screen buffer.
;
DBA MACRO ATTR,STR ; DB with attribute
IRPC C,<&STR> ;
DB '&C',ATTR ;
ENDM ;
ENDM ;
;
; Start of program area.
;
CODE SEGMENT PARA PUBLIC ;
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE ;
;
; Program Segment Prefix area.
;
MENU_PSP LABEL BYTE ; Start of segment
ORG 80H ;
P_CNT DB ? ; Number of bytes of parameter supplied
P_CMD DB ? ; Parameter area
;
; MENU Body
;
ORG 100H ;
MENU PROC ;
JMP INIT ; Go to initialization code
;
; Data area.
;
;
; Screen handling.
;
SAVEPAGE DB ? ; Save video page
SAVECRS DW ? ; Save original cursor position
FAST DB 0 ; If non-zero, fast screen update
VIDEO_SEG DW MONO_SEG ; Default video display segment
STATUS_REG DW ? ; Video status register
SCR_COL DB 80,0 ; Default screen width
SCR_LIN DB 25,0 ; Default number of lines
DISP_SIZE DW 24*80*2 ; Default display area size
DISP_LOC DW 0FFFFH ; Save area start for screen
EDIT_LAST DW ? ; Last address in edit buffer
ATTRIBUTE DB SCR_ATTR ; Current screen attribute
DOPT DW L_SCHR ; Length of screen character table
EOPT DW L_KEYT ; Length of editing character table
SHOW DB 0 ; Show fields if set
SCRN_END DW ? ; Location of end of screen
;
; Input field handling.
;
EDIT_NUM DW 0 ; Index to next input area def
EDIT_AREA DW EDIT_FLD DUP(0,0) ; Start and end of input areas
DW 0,0 ; Last DEF_AREA entry
;
; Constant fields.
;
CONST_NUM DW 0 ; Index to next constant definition
CONST_AREA DW EDIT_FLD DUP(0,0) ; Start and end of constant areas
;
; Defining new input fields.
;
DEF_NUM DW 0 ; Index to next definition
DEF_AREA EQU EDIT_AREA+4 ; Start and end of input areas
; Only use one real input area
; when defining new ones
;
; Handles and other I/O related.
;
SCREENFILE DW ? ; Screen file handle
TEMPLFILE DW ? ; Template file handle
IN_CNT DW 0 ; Characters remaining in input buffer
IN_INDX DW ? ; Next character in input buffer
NUM_OUT DW 0 ; Number of output files
OUT_HNDL LABEL WORD ;
DW 64 DUP(0) ; Output file handles
OUTFILE DW ? ; Current output file handle
OUT_INDX DW 0 ; Output buffer index
;
; Messages
;
CRLF DB CR_CHR,LF_CHR ;
BIG_MSG DB "Screen file is too long." ;
L_BIG EQU $-BIG_MSG ;
SCRN_ERR DB 'Error reading screen file.' ;
L_SERR EQU $-SCRN_ERR ;
INP_MSG DB "Screen file contains unbalanced []'s or too " ;
DB 'many fields.' ;
L_INP EQU $-INP_MSG ;
CONST_MSG DB "Screen file contains unbalanced {}'s or too " ;
DB 'many constants.' ;
L_CONST EQU $-CONST_MSG ;
ANSI_MSG DB 'Illegal ANSI (ESC) sequence. Only ESC [#;...#m ' ;
DB 'is allowed. #=0-47.' ;
L_ANSI EQU $-ANSI_MSG ;
TMPL_ERR DB 'Error reading template file.' ;
L_TMPL EQU $-TMPL_ERR ;
TMPL_MSG DB "Template file contains unbalanced []'s, {}'s, " ;
DB "<>'s or a bad field number." ;
L_TBAD EQU $-TMPL_MSG ;
OUT_MSG DB 'Error writing output file.' ;
L_OUT EQU $-OUT_MSG ;
Q_MSG DB 'Do you want to quit? YN' ;
L_Q EQU $-Q_MSG ;
ROOM_MSG DB 'Too many fields' ;
L_ROOM EQU $-ROOM_MSG ;
BAL_MSG DB 'No field start' ;
L_BAL EQU $-BAL_MSG ;
NEST_MSG DB 'Fields may not be nested' ;
L_NEST EQU $-NEST_MSG ;
COLOR_MSG DB 'Text=' ;
TCLR DB ' Bkgr=' ;
BCLR DB ' Blink=' ;
BLNK DB ' ' ;
L_COLOR EQU $-COLOR_MSG ;
;
; Date and time values
;
DOW DW 0 ; Day of week index (0-6)*3
MON DW 0 ; Month index (0-12)*3
MONTH DW 'MM' ; Month
DAY DW 'DD' ; Day
CENTURY DW 'CC' ; Century
YEAR DW 'YY' ; Year
HOUR DW 'hh' ; Hours
MINUTE DW 'mm' ; Minutes
SECOND DW 'ss' ; Seconds
DOW_TAB LABEL BYTE ; Day of week abbreviations
DB 'Sun' ;
DB 'Mon' ;
DB 'Tue' ;
DB 'Wed' ;
DB 'Thu' ;
DB 'Fri' ;
DB 'Sat' ;
MON_TAB LABEL BYTE ; Month abbreviations
DB 'Jan' ;
DB 'Feb' ;
DB 'Mar' ;
DB 'Apr' ;
DB 'May' ;
DB 'Jun' ;
DB 'Jul' ;
DB 'Aug' ;
DB 'Sep' ;
DB 'Oct' ;
DB 'Nov' ;
DB 'Dec' ;
TD_TAB LABEL WORD ; Pattern table for time/date
DW 'DW' ;
DW 'MN' ;
DW 'MM' ;
DW 'DD' ;
DW 'CC' ;
DW 'YY' ;
DW 'hh' ;
DW 'mm' ;
DW 'ss' ;
L_TD EQU ($-TD_TAB)/2 ; Number entries
TD_LOC DW DOW ;
DW MON ;
DW MONTH ;
DW DAY ;
DW CENTURY ;
DW YEAR ;
DW HOUR ;
DW MINUTE ;
DW SECOND ;
;
; Key handling tables.
;
KEY_TAB LABEL WORD ; Keys requiring special handling
DW CR_CHR ; Carriage return
DW LF_CHR ; Ctrl Enter
DW TAB_CHR ; Tab
DW ESC_CHR ; Esc
DW BS_CHR ; Backspace
DW 15*256 ; Back tab
DW 71*256 ; Home
DW 72*256 ; Up arrow
DW 73*256 ; PgUp
DW 75*256 ; Left arrow
DW 77*256 ; Right arrow
DW 79*256 ; End
DW 80*256 ; Down arrow
DW 81*256 ; PgDn
DW 82*256 ; Ins
DW 83*256 ; Del
DW 117*256 ; Ctrl End
DW 119*256 ; Ctrl Home
DW 59*256 ; F1
L_KEYT EQU ($-KEY_TAB)/2 ; Number entries if not editing screen
DW 60*256 ; F2
DW 61*256 ; F3
DW 62*256 ; F4
DW 63*256 ; F5
DW 64*256 ; F6
DW 65*256 ; F7
DW 66*256 ; F8
DW 67*256 ; F9
DW 68*256 ; F10
DW 131*256 ; Alt =
L_EDIT EQU ($-KEY_TAB)/2 ; Number of entries if editing screen
KEY_VECT LABEL WORD ; Vector for key processing routines
DW EDIT_PUT ;
DW CR_SUB ;
DW CENTER_SUB ;
DW TAB_SUB ;
DW ESC_SUB ;
DW BS_SUB ;
DW BTAB_SUB ;
DW HOME_SUB ;
DW UP_SUB ;
DW PGUP_SUB ;
DW LEFT_SUB ;
DW RIGHT_SUB ;
DW END_SUB ;
DW DOWN_SUB ;
DW PGDN_SUB ;
DW INS_SUB ;
DW DEL_SUB ;
DW CEND_SUB ;
DW CHOME_SUB ;
DW HELP_SUB ;
DW SETND_SUB ;
DW FSHOW_SUB ;
DW FDEL_SUB ;
DW CNSTRT_SUB ;
DW CNEND_SUB ;
DW FSTRT_SUB ;
DW FEND_SUB ;
DW ATTR_SUB ;
DW COLOR_SUB ;
DW FORCE_SUB ;
;
; Search and vector table for screen file conversion.
;
SCR_CHR LABEL BYTE ;
DB CR_CHR,LF_CHR,ESC_CHR ;
L_DOPT EQU $-SCR_CHR ; Length if display only
DB '\[]{}' ;
L_SCHR EQU $-SCR_CHR ;
SCR_VECT LABEL WORD ;
DW SCR_PUT ; If no match, just put character
DW SCR_CR ;
DW SCR_LF ;
DW SCR_ANSI ;
DW SCR_FORCE ;
DW SCR_LBRK ;
DW SCR_RBRK ;
DW SCR_LBRACE ;
DW SCR_RBRACE ;
;
; Search and vector table for pattern replacement.
;
REPL_CHR LABEL BYTE ;
DB '\?=|]' ;
L_RCHR EQU $-REPL_CHR ;
REPL_VECT LABEL WORD ;
DW REPL_PUT ; If no match, just put character
DW COPY_FORCE ;
DW COPY_ONE ;
DW COPY_LINE ;
DW COPY_STOP ;
DW COPY_REST ;
;
; Search and vector table for template file processing.
;
TMPL_CHR LABEL BYTE ;
DB '\[]{}<>' ;
L_TCHR EQU $-TMPL_CHR ;
TMPL_VECT LABEL WORD ;
DW TMPL_PUT ; If no match, just put character
DW TMPL_FORCE ;
DW TMPL_SENT ;
DW TMPL_ERROR ;
DW TMPL_CONST ;
DW TMPL_ERROR ;
DW TMPL_FILE ;
DW TMPL_ERROR ;
;
; Attribute tables for ANSI sequence.
;
ATTR_MASK LABEL BYTE ;
DB 0 ; White on black
DB 0FFH ; Bold
DB 0FFH ;
DB 0FFH ;
DB 0F8H ; Underline
DB 0FFH ; Blink
DB 0FFH ;
DB 077H ; Reverse video
DB 070H ; Invisible
DB 29-8 DUP(0FFH) ; Unused
DB 070H ; Black foreground
DB 070H ; Red foreground
DB 070H ; Green foreground
DB 070H ; Yellow foreground
DB 070H ; Blue foreground
DB 070H ; Magenta foreground
DB 070H ; Cyan foreground
DB 070H ; White foreground
DB 39-37 DUP(0FFH) ; Unused
DB 0FH ; Black background
DB 0FH ; Red background
DB 0FH ; Green background
DB 0FH ; Yellow background
DB 0FH ; Blue background
DB 0FH ; Magenta background
DB 0FH ; Cyan background
DB 0FH ; White background
L_ATTR EQU $-ATTR_MASK ; Number of attribute values
ATTR_VAL LABEL BYTE ;
DB 7 ; White on black
DB 8 ; Bold on
DB 0 ;
DB 0 ;
DB 1 ; Underline
DB 80H ; Blink
DB 0 ;
DB 0 ; Reverse
DB 0 ; Hidden
DB 29-8 DUP(0) ; Unused
DB 0 ; Black foreground
DB 4 ; Red foreground
DB 2 ; Green foreground
DB 6 ; Yellow foreground
DB 1 ; Blue foreground
DB 5 ; Magenta foreground
DB 3 ; Cyan foreground
DB 7 ; White foreground
DB 39-37 DUP(0) ; Unused
DB 0 ; Black background
DB 40H ; Red background
DB 20H ; Green background
DB 60H ; Yellow background
DB 10H ; Blue background
DB 50H ; Magenta background
DB 30H ; Cyan background
DB 70H ; White background
;
; Status line.
;
C10 DB 10,0 ; Constant 10
C100 DB 100 ; Constant 100
STAT_ATTR EQU 1FH ; White on blue
STATUS_MSG DB 'COL=' ;
STAT_COL DB 'xxx, ROW=' ;
STAT_ROW DB 'xxx, LN=' ;
STAT_LIN DB 'xxx' ;
DB ' ' ;
STAT_INS DB ' ' ;
DB ' ' ;
STAT_Q DB ' ' ;
DB 71-($-STATUS_MSG) DUP(' ') ;
Q_LNG EQU $-STAT_Q ; Max length of messages
DB 'F1 = Help' ;
DB 80 DUP(' ') ; Status lines up to 160 characters
;
; Menu for selecting colors and attributes.
;
COLOR_MNU LABEL WORD ;
DBA %(SCR_ATTR OR 8),< COLORS >
DBA SCR_ATTR,< > ;
DBA SCR_ATTR,<Select text color(0-15) background(0-7) > ;
DBA SCR_ATTR,< and blink(Y,N) > ;
DBA SCR_ATTR,<Press Enter when done > ;
DBA SCR_ATTR,< > ;
DBA 70H,< 0 = Black > ;
DBA 8,< 8 = Dark grey > ;
DBA 1,< 1 = Blue > ;
DBA 9,< 9 = Bright blue > ;
DBA 2,< 2 = Green > ;
DBA 10,<10 = Bright green > ;
DBA 3,< 3 = Cyan > ;
DBA 11,<11 = Bright cyan > ;
DBA 4,< 4 = Red > ;
DBA 12,<12 = Bright Red > ;
DBA 5,< 5 = Magenta > ;
DBA 13,<13 = Bright Magenta > ;
DBA 6,< 6 = Brown > ;
DBA 14,<14 = Yellow > ;
DBA 7,< 7 = White > ;
DBA 15,<15 = Bright white > ;
L_CTAB EQU ($-COLOR_MNU)/80 ; Number of lines in menu
;
; HELP display
;
HELP_MNU LABEL WORD ;
DBA %(SCR_ATTR OR 8),< KEY DEFINITIONS >
DBA SCR_ATTR,< > ;
DBA SCR_ATTR,<Press Enter when done > ;
DBA SCR_ATTR,< > ;
DBA SCR_ATTR,<Esc = Quit > ;
DBA SCR_ATTR,<Ctrl Enter = Done > ;
DBA SCR_ATTR,<F1 = Key definition > ;
DBA SCR_ATTR,<Enter = Field done > ;
DBA SCR_ATTR,<Tab = Next field > ;
DBA SCR_ATTR,<ShiftTab = Tab back > ;
DBA SCR_ATTR,<Home = Field start > ;
DBA SCR_ATTR,<End = Field end > ;
DBA SCR_ATTR,<Ctrl Home = Top > ;
DBA SCR_ATTR,<Ctrl End = Bottom > ;
DBA SCR_ATTR,<Ins = Insert mode > ;
DBA SCR_ATTR,<Del = Delete char > ;
L_HELP EQU ($-HELP_MNU)/80 ; Number of lines if not editing
DBA SCR_ATTR,<Alt= = Insert key > ;
DBA SCR_ATTR,<F2 = Set end screen > ;
DBA SCR_ATTR,<F3 = Display Fields > ;
DBA SCR_ATTR,<F4 = Delete Field > ;
DBA SCR_ATTR,<F5 = Start Constant > ;
DBA SCR_ATTR,<F6 = End Constant > ;
DBA SCR_ATTR,<F7 = Start Field > ;
DBA SCR_ATTR,<F8 = End Field > ;
DBA SCR_ATTR,<F9 = Select color > ;
DBA SCR_ATTR,<F10 = Color char > ;
L_HMNU EQU ($-HELP_MNU)/80 ; Number of lines in menu
;
; Code area.
;
BEGIN: ;
;
; Copy screen file to editing buffer.
; Editing buffer is layed out in screen format.
;
MOV DI,OFFSET EDIT_LOC ;
MOV AH,SCR_ATTR ; Default attribute
MOV BX,SCREENFILE ;
CMP DOPT,L_DOPT ; If /D option, allow STDIN
JE SCR_LINE ;
OR BX,BX ; Any screen file?
JZ SCR_DONE ; No, Just use an empty file
;
; Get next character and check for special cases.
; For CR, treat as end of line and skip an immediately following LF.
; For LF, treat as end of line.
; For ESC, process ANSI SGR sequence.
; For \, use next character even if it is a special character.
; For [], build input field
; For {}, build constant field
; For anything else, just use the character.
;
SCR_LINE: ;
MOV DX,WORD PTR SCR_COL ; Number of columns on screen
SCR_GET: ;
CALL GET_CHR ;
JZ SCR_END ; If no more characters
SCR_GOT: ;
MOV CX,DOPT ; Length for display type
MOV SI,OFFSET SCR_CHR ;
CALL TBL_SRCH ; Find character type
JMP SCR_VECT[SI] ; Branch on character type
;
; Just put the character and the current attribute in the display.
;
SCR_PUT: ;
CMP DI,EDIT_LAST ; Buffer full?
JA SCR_ERROR ; File too big
STOSW ; Store character
DEC DX ; Starting a new line on screen?
JNS SCR_GET ; No
ADD DX,WORD PTR SCR_COL ; Chars remaining in new line
JMP SCR_GET ;
;
; Got a line feed (LF) which always means end of record.
;
SCR_LF: ;
CALL SCR_PAD ; Close out line
JMP SCR_LINE ; and start another
;
; Got a CR which means end of record. Must check for a line feed following
; and skip it if found.
;
SCR_CR: ;
CALL SCR_PAD ; Close out line
MOV DL,SCR_COL ; Start new line
CALL GET_CHR ; Get next character
JZ SCR_DONE ; No more characters
CMP AL,LF_CHR ; Is it a LF?
JNE SCR_GOT ; No, go process it
JMP SCR_GET ; Yes, go get next character
;
; End of file
;
SCR_END: ;
CMP DL,SCR_COL ; Started a line?
JAE SCR_DONE ; No
CALL SCR_PAD ; Fill out line to end
SCR_DONE: ;
JMP EDIT_RDY ;
;
; Insert spaces into screen line for remainder of line.
; DX = space count
;
SCR_PAD: ;
MOV CX,DX ; Remaining character count
MOV AL,' ' ; Space character.
REP STOSW ;
MOV DX,CX ; No characters remaining
CMP DI,EDIT_LAST ; Overflow?
JA SCR_ERROR ; Yes
RET ;
;
; Expanded file is too big.
;
SCR_ERROR: ;
MOV DX,OFFSET BIG_MSG ;
MOV CX,L_BIG ;
JMP ERROR_DSP ;
;
; Found a \. Put the next character no matter what it is.
;
SCR_FORCE: ;
CALL GET_CHR ;
JZ SCR_END ;
JMP SCR_PUT ;
;
; Found a [. Start input field.
;
SCR_LBRK: ;
MOV SI,EDIT_NUM ; Loc of next input area control
CMP SI,EDIT_FLD*4 ; Already too many?
JAE INP_ERROR ; No
CMP EDIT_AREA[SI],0 ; Already started an input area?
JNZ INP_ERROR ;
MOV EDIT_AREA[SI],DI ; Save start of input area
JMP SCR_GET ; Go get next character
;
; Found a ]. End input field.
;
SCR_RBRK: ;
MOV SI,EDIT_NUM ;
CMP SI,EDIT_FLD*4 ; Already too many?
JAE INP_ERROR ; No
CMP EDIT_AREA[SI],0 ; Start of area found?
JZ INP_ERROR ; No, error
MOV EDIT_AREA[SI+2],DI ; Save end of area
ADD EDIT_NUM,4 ; Move to next area
JMP SCR_GET ;
INP_ERROR: ; Unbalanced or too many []'s
MOV DX,OFFSET INP_MSG ;
MOV CX,L_INP ;
JMP ERROR_DSP ; Go display error message
;
; Found an ANSI sequence. Form new attribute value.
;
SCR_ANSI: ;
CALL GET_CHR ; We have the Esc, look for [
JZ ANSI_ERROR ;
CMP AL,'[' ; ESC [ ?
JNE ANSI_ERROR ; No
PUSH DX ;
MOV CL,4 ;
SCR_ALP: ;
CALL DTB ; Get binary value
CMP DX,L_ATTR ; Legal attribute value?
JAE ANSI_ERROR ; No, error
MOV SI,DX ;
AND AH,ATTR_MASK[SI] ; Mask attribute to be changed out
OR AH,ATTR_VAL[SI] ; Put in new value
CMP DL,7 ; Reverse video?
JNE SCR_INV ; No
ROL AH,CL ;
SCR_INV: ;
CMP DL,8 ; Canceled(invisible)?
JNE SCR_SEP ; No
MOV DH,AH ; Make foreground=background
SHR DH,CL ;
OR AH,DH ;
SCR_SEP: ;
CMP AL,';' ; Sub-field separator?
JE SCR_ALP ; Yes, continue
CMP AL,'m' ; End of SGR sequence?
JNE ANSI_ERROR ; No
POP DX ;
JMP SCR_GET ; Yes
ANSI_ERROR: ; Not a supported Esc sequence
MOV DX,OFFSET ANSI_MSG ;
MOV CX,L_ANSI ;
JMP ERROR_DSP ;
;
; { indicating beginning of constant area.
;
SCR_LBRACE: ;
MOV SI,CONST_NUM ; Loc of next constant area control
CMP SI,EDIT_FLD*4 ; Already too many?
JAE CONST_ERROR ; No
CMP CONST_AREA[SI],0 ; Already started a constant area?
JNZ CONST_ERROR ;
MOV CONST_AREA[SI],DI ; Save start of constant area
JMP SCR_GET ; Go get next character
;
; Found a }. End constant area.
;
SCR_RBRACE: ;
MOV SI,CONST_NUM ;
CMP SI,EDIT_FLD*4 ; Already too many?
JAE CONST_ERROR ; No
CMP CONST_AREA[SI],0 ; Start of area found?
JZ CONST_ERROR ; No, error
MOV CONST_AREA[SI+2],DI ; Save end of area
ADD CONST_NUM,4 ; Move to next area
JMP SCR_GET ;
CONST_ERROR: ;
MOV CX,L_CONST ;
MOV DX,OFFSET CONST_MSG ;
JMP ERROR_DSP ;
;
; Check for unbalanced []'s and {}'s.
;
EDIT_RDY: ;
MOV SI,EDIT_NUM ;
CMP SI,EDIT_FLD*4 ; Area full?
JAE EDIT_BRACE ; Yes, everything is OK
CMP EDIT_AREA[SI],0 ; Started next field?
JZ EDIT_BRACE ; No
JMP INP_ERROR ; Yes, error
EDIT_BRACE: ;
MOV SI,CONST_NUM ;
CMP SI,EDIT_FLD*4 ; Full?
JAE EDIT_OK ;
CMP CONST_AREA[SI],0 ; Started next constant.
JNZ CONST_ERROR ;
EDIT_OK: ;
DEC DI ; Update end of file
DEC DI ;
;
; If the /E option is set, copy all existing input field definitions to the
; New field area and set the entire display to a single input field.
;
CMP EOPT,L_EDIT ; Editing a screen file?
JNE EDIT_NORM ; No normal file editing
MOV CX,EDIT_NUM ; Length to copy
MOV SI,OFFSET EDIT_AREA-1 ; Copy input definition to
ADD SI,CX ;
MOV DI,OFFSET DEF_AREA-1 ; new input definitions
ADD DI,CX ;
MOV DEF_NUM,CX ;
STD ; Overlapping fields
REP MOVSB ;
CLD ;
MOV EDIT_NUM,4 ; Define a single input field
MOV EDIT_AREA,OFFSET EDIT_LOC ; covering the entire file
MOV DI,EDIT_LAST ;
MOV EDIT_AREA+2,DI ;
MOV SCRN_END,DI ; Default end of screen definition
EDIT_NORM: ;
MOV EDIT_LAST,DI ;
CMP DI,OFFSET EDIT_LOC-2 ; Empty file?
JA EDIT_NMT ; No
JMP CENTER_SUB ; Yes, just exit
EDIT_NMT: ;
;
; Display first screen of file.
;
CALL CHOME_SUB ; Display first page
;
; Now get a key and process editing commands.
;
EDIT_FILE: ;
XOR AH,AH ;
INT KYBD$ ; Read next character
OR AL,AL ; Extended key?
JZ EDIT_XTND ; Yes
XOR AH,AH ; Clear scan code
EDIT_XTND: ;
;
; Determine type of key and switch to proper routine to handle that key type.
;
PUSH SI ;
MOV CX,EOPT ;
MOV SI,OFFSET KEY_TAB ;
CALL WTBL_SRCH ; Find matching entry
MOV BX,SI ;
POP SI ;
CALL KEY_VECT[BX] ; Go to key routine
JMP EDIT_FILE ;
;
; Put character in file and display. All normal keys.
;
EDIT_PUT: ;
CMP AL,0 ; Don't put NULs
JZ EDIT_STATUS ;
EDIT_FORCE: ;
CALL FIND_AREA ; Are we in an input field?
JC EDIT_STATUS ; No, do nothing
CMP STAT_INS,' ' ; Are we inserting?
JE EDIT_NINS ; No, just store the character
;
; Insert a character in this input area.
;
PUSH DI ;
PUSH SI ;
MOV DI,EDIT_AREA[BX+2] ; Amount to move
DEC DI ;
DEC DI ;
CMP SI,DI ; At end of area?
JAE EDIT_NMV ; Yes, don't move anything
MOV CX,DI ;
SUB CX,SI ;
LEA SI,[DI-2] ;
SHR CX,1 ;
STD ;
REP MOVSW ; Copy characters
CLD ;
EDIT_NMV: ;
POP SI ;
POP DI ;
MOV [SI],AL ;
CALL DISP_SCREEN ; Display the modified field
JMP SHORT RIGHT_SUB ;
;
; Put character in file buffer and display.
;
EDIT_NINS: ;
MOV [SI],AL ; Put key in file
MOV AH,[SI+1] ;
CALL WRITE_SCREEN ;
DEC DI ; Don't move cursor here
DEC DI ;
;
; Increment cursor position.
;
RIGHT_SUB: ; Right arrow
MOV AX,1 ;
;
; General logic to move the cursor.
; If it would move outside the file, it is moved the maximum amount.
; If it moves outside the current screen, the screen is moved.
; This logic is only good for moves of <8000H bytes.
; Entered with AX = Amount to move cursor, positive or negative.
;
MOVE_CRS: ;
CWD ; Extend sign
SHL AX,1 ; Make into word offset
ADD AX,SI ; Adjust file pointer
ADC DX,0 ;
JS CHOME_SUB ; Negative is before start
JNZ CEND_SUB ; Too large, so after end
CMP AX,OFFSET EDIT_LOC ; Before start of file?
JB CHOME_SUB ; Yes
CMP AX,EDIT_LAST ; Beyond end?
JA CEND_SUB ; Yes
;
; Move to a specific display position.
; Because we could be moving 16384 (8000H) bytes or more, we must handle the
; calculations with double precision arithmetic.
; Enter with AX = New display position.
;
MOVE_TO: ;
XCHG SI,AX ; New file position
SUB AX,SI ; Distance from old to new
SBB DX,DX ; Sign extend distance to high order
SUB DI,AX ; New cursor index
ADC DX,0 ; Slight cheat knowing sign of DI
JS MOVE_FWD ; DI>64K, move screen forward
JNZ MOVE_BACK ; DI<0, move screen backward
CMP DI,DISP_SIZE ; Off end of screen?
JAE MOVE_FWD ; Must move screen forward
CALL FIND_AREA ; Get next input field
JNC EDIT_STATUS ; Already in one
MOV AX,EDIT_AREA[BX] ; Start of next area
SUB AX,SI ; Offset to start of next area
JB EDIT_STATUS ; Don't move back to area
MOV CX,AX ;
ADD CX,DI ; Cursor index of next area
SHR AX,1 ;
CMP CX,DISP_SIZE ; Still on screen?
JB MOVE_CRS ; Yes, move cursor to input area
;
; Update status line with cursor position and move video cursor.
;
EDIT_STATUS: ;
CALL STAT_CLR ; Clear any message in status line
CALL STATUS ; Display status line
XOR BH,BH ; Video page 0
MOV AX,DI ;
SHR AX,1 ;
DIV SCR_COL ; Compute new cursor position
XCHG AL,AH ;
MOV DX,AX ;
MOV AH,CRS$ ; Update cursor position
INT VIDEO$ ;
RET ;
;
; Ctrl Home = Go to top of display.
;
CHOME_SUB: ; Ctrl Home
MOV SI,OFFSET EDIT_LOC ; Move back to start
;
; Move display back until new position is in first line on screen.
;
MOVE_BACK: ;
XOR DI,DI ; Cursor line is top of screen
JMP SHORT MOVE_SCRN ;
;
; Move display forward until new position is in last line on screen.
;
MOVE_FWD: ;
MOV DI,DISP_SIZE ;
SUB DI,WORD PTR SCR_COL ; Cursor is in last line
SUB DI,WORD PTR SCR_COL ;
MOVE_SCRN: ;
LEA AX,[SI-(OFFSET EDIT_LOC - OFFSET MENU_PSP)] ;
SHR AX,1 ;
CWD ; May be more than 256 lines
DIV WORD PTR SCR_COL ; Compute new column position
SHL DX,1 ; Remainder is column
ADD DI,DX ; New cursor position
CALL DISP_SCREEN ; Redisplay screen
XOR AX,AX ; Find field position
JMP MOVE_CRS ;
;
; Ctrl End = Go to end of display.
;
CEND_SUB: ; Ctrl End
MOV AX,EDIT_LAST ; Move to end of display area
JMP MOVE_TO ;
;
; CR = Go to next line in a multi-line field, or to next field, or exit
; if in last line of last field.
;
CR_SUB: ; CR
CALL FIND_AREA ; Find which area we are in
JC CR_TAB ; Not in an area
MOV AX,DI ;
SHR AX,1 ;
DIV SCR_COL ; Offset to start of next line
MOV AL,SCR_COL ;
SUB AL,AH ;
XOR AH,AH ;
SHL AX,1 ;
ADD AX,SI ;
CMP AX,EDIT_AREA[BX+2] ; Beyond end of area?
JB GO_MTO ; No, just move to next line
ADD BX,4 ;
CR_TAB: ; Go to next area or quit
CMP BX,EDIT_NUM ; In last field?
JAE GO_CENTER ; Yes
CMP SI,EDIT_AREA[BX] ; After last field?
JB TAB_SUB ; No, move to next field
GO_CENTER: ;
JMP CENTER_SUB ; Yes, end of entry
;
; Down arrow = Move down one line.
;
DOWN_SUB: ; Down arrow
MOV AX,WORD PTR SCR_COL ; Move one line
JMP MOVE_CRS ;
;
; Up arrow = Move up one line.
;
UP_SUB: ; Up arrow
MOV AX,WORD PTR SCR_COL ; Move up one line
NEG AX ;
JMP MOVE_CRS ;
;
; PgUp = Move up one page.
;
PGUP_SUB: ; PgUp
MOV AX,DISP_SIZE ;
SHR AX,1 ;
NEG AX ; Move back one page
JMP MOVE_CRS ; Move to next input area if any
;
; PgDn = Move down one page.
;
PGDN_SUB: ; PgDn
MOV AX,DISP_SIZE ; Move ahead one screen
SHR AX,1 ;
JMP MOVE_CRS ;
;
; Tab = Move to start of next field.
;
TAB_SUB: ; TAB
CMP EDIT_NUM,0 ; Any input areas?
JZ GO_EST ; No, nothing to do
CALL FIND_AREA ; Find current area
JC TAB_OK ; Point to next area
ADD BX,4 ; Move to next area
CMP BX,EDIT_NUM ; Wrap around?
JB TAB_OK ;
XOR BX,BX ;
TAB_OK: ;
MOV AX,EDIT_AREA[BX] ; Move to start of next area
GO_MTO: ;
JMP MOVE_TO ;
;
; Home and Back tab = Move to start of this field. If at start, move to
; start of previous field.
;
HOME_SUB: ; Home
BTAB_SUB: ; Back tab
CALL FIND_AREA ; Find current area
JC BTAB_AREA ; Not in an area, just use previous
MOV AX,EDIT_AREA[BX] ;
CMP AX,SI ; Already at start of area?
JNE GO_MTO ; No, move to start of area
BTAB_AREA: ;
CMP EDIT_NUM,0 ; Any input areas?
JZ GO_EST ; No
OR BX,BX ; First area?
JNZ BACK_AREA ; No
MOV BX,EDIT_NUM ; Yes, move to last area
BACK_AREA: ;
MOV AX,EDIT_AREA[BX-4] ; Start of previous area
JMP MOVE_TO ;
GO_EST: ;
JMP EDIT_STATUS ;
;
; Left arrow = Move cursor left one space.
;
LEFT_SUB: ; Left arrow
MOV AX,-1 ; Back one space
JMP MOVE_CRS ;
;
; End = Move to end of this field. Moves to first space after last non-space.
;
END_SUB: ; End
CALL FIND_AREA ; Find area
CMP BX,EDIT_NUM ; Any areas?
JAE GO_EST ; No, nothing to do
CALL END_FIND ; Find end of next area
CMP AX,SI ; Would we move?
JNE GO_MTO ; Yes, so move
CALL TAB_SUB ; Move to end of next area
CALL FIND_AREA ;
CALL END_FIND ;
JMP MOVE_TO ;
;
; Find end of area.
;
END_FIND: ;
PUSH DI ;
MOV DX,EDIT_AREA[BX] ; Start of area
MOV DI,EDIT_AREA[BX+2] ; End of area
MOV AH,[DI-1] ; Attribute for first position
CALL TRIM ; Find last non-blank + 2
CMP DI,EDIT_AREA[BX+2] ; Non-blank in last position
JB EF_LAST ; No
DEC DI ; Go to last position then
DEC DI ;
EF_LAST: ;
MOV AX,DI ; Position to move to
POP DI ;
RET ;
;
; Ins = Toggle insert mode.
;
INS_SUB: ;
XOR STAT_INS,' ' XOR '^' ; Toggle insert mode
JMP EDIT_STATUS ; Go display updated status
;
; Backspace = Move back one space and delete the character there.
; If at first character of the field, do nothing.
;
BS_SUB: ; Backspace
CALL FIND_AREA ; Find current input area
JC LEFT_SUB ; Not in area, just move left
CMP SI,EDIT_AREA[BX] ; Are we at start?
JNE BS_LFT ; No, move left
JMP EDIT_STATUS ; Nothing to do
BS_LFT: ;
CALL LEFT_SUB ;
;
; Del = Delete the character under the cursor.
;
DEL_SUB: ;
CALL FIND_AREA ; Find the area we are in
JC GO_EST ; Not in an area
MOV CX,EDIT_AREA[BX+2] ;
DEC CX ; Last character of field
DEC CX ;
PUSH CX ; Save last position
SUB CX,SI ;
PUSH DI ;
PUSH SI ;
MOV DI,SI ;
INC SI ;
INC SI ;
REP MOVSB ; Copy characters
POP SI ;
POP DI ;
POP BX ;
MOV BYTE PTR [BX],' ' ; Put a blank in the last spot
CALL DISP_SCREEN ; Display the field
RET ;
;
; F1 = Help. Display key definitions.
;
HELP_SUB: ;
MOV AX,OFFSET HELP_MNU ;
MOV CX,L_HELP ; Length if not editing
CMP EOPT,L_EDIT ; Editing a screen file?
JNE HELP_NRM ; No
MOV CX,L_HMNU ;
HELP_NRM: ;
CALL DISP_MNU ; Display the menu
HELP_WT: ;
XOR AH,AH ;
INT KYBD$ ;
CMP AL,ESC_CHR ;
JE HELP_QUIT ;
CMP AL,CR_CHR ;
JNE HELP_WT ; Wait for a CR
HELP_QUIT: ;
CALL DISP_SCREEN ; Refresh the screen
JMP EDIT_STATUS ;
;
; F2 = Send end of screen definition location.
;
SETND_SUB: ;
MOV SCRN_END,SI ; Set new end of definition loc
JMP EDIT_STATUS ;
;
; F3 = Toggle field and constant display.
;
FSHOW_SUB: ;
XOR SHOW,1 ; Toggle show flag
CALL DISP_SCREEN ; Redisplay this screen
RET ;
;
; F4 = Erase field or constant definition at this location.
;
FDEL_SUB: ; Erase definition
XOR BX,BX ; Loop through all definitions
FDEL_LP: ;
CMP BX,DEF_NUM ;
JAE NO_FDEF ;
CMP SI,DEF_AREA[BX] ; Start of this field?
JNE NO_FDEF ; No
MOV AX,OFFSET DEF_AREA ;
CALL FD_RMV ; Remove entry
SUB DEF_NUM,4 ; Reduce count of entries
JMP FDEL_LP ; Check next entry
NO_FDEF: ;
CMP BX,CONST_NUM ;
JAE NO_FCON ;
CMP SI,CONST_AREA[BX] ; Start of this constant?
JNE NO_FCON ; No
MOV AX,OFFSET CONST_AREA ;
CALL FD_RMV ; Remove entry
SUB CONST_NUM,4 ; Reduce count
JMP NO_FDEF ; Check next entry
NO_FCON: ;
ADD BX,4 ;
CMP BX,EDIT_FLD*4 ; More fields to check?
JB FDEL_LP ; Yes
CALL DISP_SCREEN ; Update display
RET ;
FD_RMV: ;
PUSH DI ; Remove this entry
PUSH SI ;
MOV CX,EDIT_FLD*4-4 ;
SUB CX,BX ; Length to move
MOV DI,BX ;
ADD DI,AX ;
LEA SI,[DI+4] ;
REP MOVSB ; Copy entries
XOR AX,AX ;
STOSW ;
STOSW ; Clear last entry
POP SI ;
POP DI ;
RET ;
;
; F5 = Start constant area.
;
CNSTRT_SUB: ; Define new constant area
MOV BX,CONST_NUM ; Pointer to next field definition
CMP BX,EDIT_FLD*4 ; Area full?
JAE DEF_ERROR ; Yes
CMP CONST_AREA[BX],0 ; Already started the area?
JNZ DEF_NEST ; Yes, cannot nest
MOV CONST_AREA[BX],SI ; Save start of area
CALL DISP_SCREEN ;
RET ;
;
; F6 = End of constant area.
;
CNEND_SUB: ; End constant area
MOV BX,CONST_NUM ;
CMP BX,EDIT_FLD*4 ; Full?
JAE DEF_ERROR ;
CMP CONST_AREA[BX],0 ; Started area?
JZ DEF_UNBAL ; No
LEA AX,[SI+2] ;
MOV CONST_AREA[BX+2],AX ; Save end of area
ADD CONST_NUM,4 ;
CALL DISP_SCREEN ;
RET ;
;
; F7 = Start new field.
;
FSTRT_SUB: ; F7
MOV BX,DEF_NUM ; Pointer to next field definition
CMP BX,EDIT_FLD*4 ; Area full?
JAE DEF_ERROR ; Yes
CMP DEF_AREA[BX],0 ; Already started the area?
JNZ DEF_NEST ; Yes, cannot nest
MOV DEF_AREA[BX],SI ; Save start of area
CALL DISP_SCREEN ;
RET ;
DEF_ERROR: ;
MOV AX,OFFSET ROOM_MSG ;
MOV CX,L_ROOM ;
CALL STAT_MSG ; Display error in status line
JMP EDIT_FILE ;
DEF_NEST: ;
MOV AX,OFFSET NEST_MSG ;
MOV CX,L_NEST ;
CALL STAT_MSG ;
JMP EDIT_FILE ;
;
; F8 = End of new field.
;
FEND_SUB: ;
MOV BX,DEF_NUM ;
CMP BX,EDIT_FLD*4 ; Full?
JAE DEF_ERROR ;
CMP DEF_AREA[BX],0 ; Started area?
JZ DEF_UNBAL ; No
LEA AX,[SI+2] ;
MOV DEF_AREA[BX+2],AX ; Save end of area
ADD DEF_NUM,4 ;
CALL DISP_SCREEN ;
RET ;
DEF_UNBAL: ;
MOV AX,OFFSET BAL_MSG ;
MOV CX,L_BAL ;
CALL STAT_MSG ;
JMP EDIT_FILE ;
;
; F9 = Select new colors.
;
ATTR_SUB: ;
;
; Display color menu.
;
MOV CX,L_CTAB ; Number of lines
MOV AX,OFFSET COLOR_MNU ;
CALL DISP_MNU ; Display attribute menu
;
; Display status line showing current colors as defaults.
;
MOV AL,[SI+1] ; Get text color
AND AL,0FH ;
CALL BTD ;
MOV WORD PTR TCLR,AX ;
MOV AL,[SI+1] ;
MOV AH,'N' ; Blink Value
TEST AL,80H ; Is it blinking?
JZ NOT_BLINK ; No
MOV AH,'Y' ;
NOT_BLINK: ;
MOV BLNK,AH ;
MOV CL,4 ;
SHR AL,CL ;
AND AL,7 ; Background color
CALL BTD ;
MOV BCLR,AH ;
;
; Get new color values.
;
PUSH SI ;
MOV DH,SCR_LIN ;
DEC DH ;
COLOR_ST: ;
MOV DL,OFFSET STAT_Q - OFFSET STATUS_MSG ;
ADD DL,OFFSET TCLR - OFFSET COLOR_MSG ;
MOV SI,OFFSET TCLR ;
XOR BH,BH ;
COLOR_LP: ;
MOV AX,OFFSET COLOR_MSG ; Put in status line
MOV CX,L_COLOR ;
CALL STAT_MSG ;
MOV AH,CRS$ ;
INT VIDEO$ ; Set cursor position
XOR AH,AH ;
INT KYBD$ ; Get next input
CMP AL,'0' ; Digit?
JB NOT_CDIG ; No
CMP AL,'9' ;
JA NOT_CDIG ;
CMP SI,OFFSET BCLR ; Blink field?
JA COLOR_LP ; Yes, no digits
MOV [SI],AL ; Put digit
CMP SI,OFFSET TCLR ; Moving to another field?
JA PUT_CLR2 ;
INC SI ;
INC DL ;
JMP COLOR_LP ;
PUT_CLR2: ;
CMP SI,OFFSET BCLR ; Moving to blink field?
JAE PUT_BKGR ; Yes
ADD SI,OFFSET BCLR - OFFSET TCLR - 1 ;
ADD DL,OFFSET BCLR - OFFSET TCLR - 1 ;
JMP COLOR_LP ;
PUT_BKGR: ;
ADD SI,OFFSET BLNK - OFFSET BCLR ;
ADD DL,OFFSET BLNK - OFFSET BCLR ;
JMP COLOR_LP ;
NOT_CDIG: ;
CMP AL,ESC_CHR ; Quit?
JE CLR_QUIT ;
CMP AL,CR_CHR ; Done?
JE CLR_DONE ; Yes
CMP AL,BS_CHR ; Backspace?
JE CLR_BS ; Yes
CMP SI,OFFSET BLNK ; Blink field?
JNE COLOR_LP ; No
AND AL,NOT 20H ;
CMP AL,'N' ;
JE PUT_BLNK ;
CMP AL,'Y' ;
JNE COLOR_LP ;
PUT_BLNK: ;
MOV [SI],AL ;
JMP COLOR_LP ;
;
; We have the color request. Convert the values and check if legal.
;
CLR_DONE: ;
MOV AL,TCLR ; Convert foreground color to binary
SUB AL,'0' ;
MUL C10 ;
ADD AL,TCLR+1 ;
SUB AL,'0' ;
MOV AH,BCLR ; Convert background color
SUB AH,'0' ;
CMP AL,15 ; Legal colors?
JA GO_CST ; No
CMP AH,7 ;
JA GO_CST ;
MOV CL,4 ; Put in attribute format
SHL AH,CL ;
OR AL,AH ;
CMP BLNK,'Y' ; Blink?
JNE NOT_BLNK ; No
OR AL,80H ;
NOT_BLNK: ;
MOV ATTRIBUTE,AL ; Save new attribute
CLR_QUIT: ;
POP SI ;
CALL DISP_SCREEN ; Redisplay screen
JMP EDIT_STATUS ; Redisplay cursor
;
; Handle backspacing in color information.
;
CLR_BS: ;
CMP SI,OFFSET TCLR+1 ; In first field?
JA BS_BKGR ; No
JB GO_CLRLP ;
DEC SI ;
DEC DL ;
GO_CLRLP: ;
JMP COLOR_LP ;
BS_BKGR: ;
CMP SI,OFFSET BCLR ; In background?
JA BS_BLNK ; No
SUB SI,OFFSET BCLR - OFFSET TCLR - 1 ;
SUB DL,OFFSET BCLR - OFFSET TCLR - 1 ;
JMP COLOR_LP ;
BS_BLNK: ;
SUB SI,OFFSET BLNK - OFFSET BCLR ;
SUB DL,OFFSET BLNK - OFFSET BCLR ;
JMP COLOR_LP ;
GO_CST: ;
JMP COLOR_ST ;
;
; F10 = Put new attribute in character and advance cursor.
;
COLOR_SUB: ;
MOV AH,ATTRIBUTE ;
MOV [SI+1],AH ; Put new attribute
MOV AL,[SI] ;
JMP EDIT_NINS ; Redisplay the character position
;
; Alt= = Put next key value whatever it is.
;
FORCE_SUB: ;
XOR AH,AH ;
INT KYBD$ ; Get next key stroke
JMP EDIT_FORCE ; and force into file
;
; Ctrl Enter = Done
;
CENTER_SUB: ; Ctrl Enter = Done
POP AX ; Throw away return
CALL REST_VID ; Restore screen
CALL GET_TIME ; Initialize date & time variables
;
; Read template file.
;
MOV BX,TEMPLFILE ; Read template file
MOV IN_CNT,0 ; Start new buffer
MOV AH,SCR_ATTR ; Starting attribute for ANSI conversion
MOV DX,1 ; First field for screen file editing
CMP EOPT,L_EDIT ; Editing a screen file?
JE DO_INP ; Yes, go copy the screen
CMP BX,0 ; Any template file?
JZ GO_DONE ; No
;
; Scan template file looking for. Check character type and handle as needed.
;
TMPL_LP: ;
CALL GET_CHR ; Get next character
JNZ TMPL_OK ; Got a character
GO_DONE: ;
JMP WF_DONE ;
TMPL_OK: ;
MOV CX,L_TCHR ;
MOV SI,OFFSET TMPL_CHR ;
CALL TBL_SRCH ; Find character type
JMP TMPL_VECT[SI] ; Switch on character type
TMPL_PUT: ;
CALL OUT_CHR ; No, send character to output
JMP TMPL_LP ; Continue processing characters
;
; \ Force out next character.
;
TMPL_FORCE: ;
CALL GET_CHR ; Get character
JNZ TMPL_PUT ; If none, error. Otherwise put it
;
; Bad template file format.
;
TMPL_ERROR: ;
MOV CX,L_TBAD ;
MOV DX,OFFSET TMPL_MSG ;
JMP ERROR_DSP ;
;
; < Switch output files.
;
TMPL_FILE: ;
CALL DTB ; Get file number
CMP AL,'>' ;
JNE TMPL_ERROR ; Not correct closing symbol
DEC DX ;
MOV SI,DX ;
SHL SI,1 ;
CMP DX,NUM_OUT ; Legal value?
JAE TMPL_ERROR ;
CALL WR_OUT ; Spill rest of buffer for current file
MOV OUT_INDX,0 ;
MOV AX,OUT_HNDL[SI] ; Get handle
MOV OUTFILE,AX ;
JMP TMPL_LP ;
;
; [ Look for pattern type.
;
TMPL_SENT: ;
;
; Check for an input area reference.
;
CALL DTB ; Convert value to binary
OR DX,DX ; Input number?
JNZ DO_INP ;
JMP CHK_PAT ; No, check if time/date pattern
;
; We have an input area to copy. Check to see if the number is good.
;
DO_INP: ;
DEC DX ;
SHL DX,1 ; Convert to area index
SHL DX,1 ;
CMP DX,EDIT_NUM ; Legal area?
JAE TMPL_ERROR ; No, error
;
; Get area to copy.
; We will not copy trailing blanks from the input area.
; Input will be treated as a single character string with no CR,LFs inserted.
; The template may indicate formatting by following the number with any of
; the following pattern characters:
; ] = All remaining input characters
; ? = Next input character
; = = All input characters up to end of screen line
; | = Ignore rest of template if no more input
; \ = Include next template character in output
; All other characters in the template are copied to the output.
;
MOV DI,DX ; Input area index
MOV DX,EDIT_AREA[DI] ; Start of input area
MOV DI,EDIT_AREA[DI+2] ; End of input area
;
; Find last non-blank.
;
CALL TRIM ; Find start of trailing spaces
XCHG DX,DI ; DX=End, DI=Start
;
; Scan template doing the replacement.
;
CMP EOPT,L_EDIT ; Editing a screen file?
JNE REPL_FIRST ; Already have first character
JMP COPY_SCRN ; Yes
REPL_INP: ;
CALL GET_CHR ; Get next template character
JZ TMPL_ERROR ;
REPL_FIRST: ;
MOV CX,L_RCHR ;
MOV SI,OFFSET REPL_CHR ;
CALL TBL_SRCH ; Get character type
CALL REPL_VECT[SI] ; Switch on character type
JMP REPL_INP ;
;
; All non-pattern characters.
;
REPL_PUT: ;
CALL OUT_CHR ; Just send the character to output
REPL_OK: ;
RET ; Continue replacing
GO_STOP: ;
JMP COPY_STOP ;
;
; \ Copy the next template character.
;
COPY_FORCE: ;
CALL GET_CHR ; Get the character
JZ TMPL_ERROR ;
JMP REPL_PUT ;
;
; ? Copy the next input character.
;
COPY_ONE: ;
CMP DI,DX ; Any left?
JAE REPL_OK ; No, nothing to copy
MOV AL,[DI] ;
INC DI ;
INC DI ;
JMP REPL_PUT ;
;
; Copy to file in screen file format. Generate ANSI sequences as needed.
; For start and end of defined input fields insert [ and ].
; For start and end of constant fields insert { and }.
; Put a \ in front of screen file control characters that appear as data.
;
COPY_SCRN: ;
CMP DX,SCRN_END ; Past user defined end?
JBE COPY_SOK ; No
MOV DX,SCRN_END ;
INC DX ;
INC DX ;
COPY_SOK: ;
CALL COPY_LINE ; Copy one line
MOV AL,CR_CHR ;
CALL OUT_CHR ;
MOV AL,LF_CHR ; Put end of line
CALL OUT_CHR ;
CMP DI,DX ; Any input left?
JB COPY_SOK ; Yes
JMP WF_DONE ; No
;
; = Copy all input characters up to the end of the screen line.
; Do not copy trailing blanks on the screen line but do skip over them.
;
COPY_LINE: ;
PUSH CX ;
PUSH AX ;
MOV AX,DI ; Starting location
SUB AX,OFFSET EDIT_LOC ; Index
SHR AX,1 ; Convert to character index
MOV CX,WORD PTR SCR_COL ; Columns per line
DIV CL ;
SUB CL,AH ; Remaining characters to end of line
MOV AX,DX ;
SUB AX,DI ;
SHR AX,1 ; Remaining characters in input field
CMP AX,CX ; Use lesser
JAE LINE_COPY ;
MOV CX,AX ;
LINE_COPY: ;
POP AX ;
JCXZ LINE_DONE ;
PUSH DX ;
MOV DX,DI ; Start of area
ADD DI,CX ; End of input area to be copied
ADD DI,CX ;
PUSH DI ; Save end
CALL TRIM ; Ignore trailing blanks
MOV CX,DI ; Compute new length
SUB CX,DX ;
SHR CX,1 ;
MOV DI,DX ; Start of copy
JCXZ LINE_MT ; All blank line
;
; Now copy the characters checking for start and end of input areas and
; change of attributes.
;
LINE_CP: ;
CMP EOPT,L_EDIT ; Generating screen file?
JNE LINE_PUT ; No
MOV AL,'[' ; Do start of fields
CALL FIELD_GEN ; Check for field start
CMP AH,[DI+1] ; Attributes match?
JNE GEN_ANSI ; No, generate ANSI sequence
LINE_CHR: ;
MOV DX,CX ;
MOV AL,[DI] ; Get next input character
MOV CX,L_SCHR ; See if this is a screen control char
MOV SI,OFFSET SCR_CHR ;
CALL TBL_SRCH ;
MOV CX,DX ;
CMP SI,0 ; Normal character?
JZ LINE_PUT ; Yes
MOV DL,AL ;
MOV AL,'\' ; Send force character
CALL OUT_CHR ;
MOV AL,DL ;
LINE_PUT: ;
MOV AL,[DI] ; Get next input character
CALL OUT_CHR ; Send to output
INC DI ;
INC DI ;
CMP EOPT,L_EDIT ; Screen file editing?
JNE LINE_ELP ; No
MOV AL,']' ; Do end of fields
CALL FIELD_GEN ;
LINE_ELP: ;
LOOP LINE_CP ;
LINE_MT: ;
POP DI ; Move to end of line
POP DX ;
LINE_DONE: ;
POP CX ;
RET ;
;
; Generate ANSI sequence from change in attribute.
;
GEN_ANSI: ;
PUSH CX ;
PUSH DX ;
XOR CX,CX ; No values output yet
;
; Put Esc [ start of ANSI sequence.
;
MOV AL,ESC_CHR ; Start ANSI sequence
CALL OUT_CHR ;
MOV AL,'[' ;
CALL OUT_CHR ;
;
; Check to see if foreground colors are changed.
;
MOV DL,[DI+1] ; Isolate foregrounds
MOV DH,AH ;
AND DX,0F0FH ;
CMP DL,DH ; Did foreground change?
JE NOT_FORE ; No
AND DL,7 ; Check to see if only intensity
CMP DL,DH ;
JE SET_INT ; Only intensity being set
TEST DL,5 ; Switch attributes if appropriate
JPE NSW_1 ;
XOR DL,5 ; Invert attributes
NSW_1: ;
MOV AL,'3' ; Put foreground color
CALL OUT_CHR ;
MOV AL,DL ;
ADD AL,'0' ;
CALL OUT_CHR ;
INC CX ;
;
; Foreground changed, so check to see if we need to set high intensity.
;
MOV DL,[DI+1] ;
TEST DL,8 ; High intensity set?
JZ NOT_FORE ; No
MOV AL,';' ;
CALL OUT_CHR ;
SET_INT: ;
MOV AL,'1' ;
CALL OUT_CHR ;
INC CX ;
NOT_FORE: ;
MOV DH,AH ;
MOV DL,[DI+1] ; Compare backgrounds
AND DX,7070H ;
CMP DL,DH ; Did background change?
JE NOT_BKGR ; No
TEST DL,50H ; Switch attributes if appropriate
JPE NSW_2 ;
XOR DL,50H ;
NSW_2: ;
JCXZ NO_SEP2 ; No value output yet
MOV AL,';' ; Put separator
CALL OUT_CHR ;
NO_SEP2: ;
MOV AL,'4' ;
CALL OUT_CHR ; Put background color
MOV AL,DL ;
MOV CL,4 ;
SHR AL,CL ;
ADD AL,'0' ;
CALL OUT_CHR ;
NOT_BKGR: ;
TEST BYTE PTR [DI+1],80H ; Blink set?
JZ NOT_BLI ; No
JCXZ NO_SEP3 ;
MOV AL,';' ; Separator
CALL OUT_CHR ;
NO_SEP3: ;
MOV AL,'5' ;
CALL OUT_CHR ;
NOT_BLI: ;
MOV AL,'m' ; Put terminator
CALL OUT_CHR ;
MOV AH,[DI+1] ; New attribute
POP DX ;
POP CX ;
JMP LINE_CHR ;
;
; | Stop copying from this template if there is no more input.
;
COPY_STOP: ;
CMP DI,DX ; Any more input?
JAE COPY_SKIP ; No
RET ; Yes
COPY_SKIP: ;
CALL GET_CHR ; Skip to end of template
JZ BAD_TP ;
CMP AL,']' ; End of template?
JE COPY_DONE ; Yes
CMP AL,'\' ; Force?
JNE COPY_SKIP ; No, keep looking
CALL GET_CHR ; Ignore next character
JZ BAD_TP ;
JMP COPY_SKIP ; Keep looking
;
; ] Copy remaining input characters to output and then start over at top.
;
COPY_REST: ;
CMP DI,DX ; Any remaining input characters?
JAE COPY_DONE ; No
MOV AL,[DI] ;
CALL OUT_CHR ; Copy to output
INC DI ;
INC DI ;
JMP COPY_REST ;
BAD_TP: ;
POP AX ;
JMP TMPL_ERROR ;
COPY_DONE: ;
POP AX ;
JMP TMPL_LP ; Continue working on template file
;
; Check for time and date patterns.
; \ Force next character
; MM DD CC YY DW MN hh mm ss are all replaced with appropriate values.
;
CHK_PAT: ;
PUSH AX ;
CHK_MORE: ;
CMP AL,']' ; End sentinel?
JE COPY_DONE ; Yes, look for next template
MOV AH,AL ; Save first pattern character
CALL GET_CHR ; Get second pattern character
JZ BAD_TP ;
PAT_CHK: ;
CMP AH,'\' ; Force next character?
JE PAT_NEXT ; Yes
MOV SI,OFFSET TD_TAB ; Pattern table
MOV CX,L_TD ;
CALL WTBL_SRCH ; Find matching entry
CMP SI,0 ; Do we have a pattern?
JNZ REPL_PAT ; Yes
XCHG AL,AH ; No, output first char and continue
CALL OUT_CHR ; Send character to output
XCHG AL,AH ;
JMP CHK_MORE ; Keep checking for patterns
;
; \ Found a force character.
;
PAT_NEXT: ;
CALL OUT_CHR ; Send forced character to output
PAT_GET: ;
CALL GET_CHR ;
JZ BAD_TP ;
JMP CHK_MORE ;
;
; Found a pattern to be replaced.
; Check for DW and MN case and handle specially.
;
REPL_PAT: ;
MOV DI,TD_LOC[SI-2] ; Data loc
CMP SI,4 ; DW or MN?
JE CK_MON ; MN
JB CK_DOW ; DW
DO_2: ;
MOV AX,[DI] ; Get data
CALL OUT_CHR ; Put in output
MOV AL,AH ;
CALL OUT_CHR ;
JMP PAT_GET ;
CK_MON: ;
MOV AX,OFFSET MON_TAB ; Month abbreviation table
DO_3: ;
ADD AX,[DI] ;
MOV DI,AX ;
MOV AL,[DI] ; Get abbreviation
CALL OUT_CHR ; Put first character
INC DI ;
JMP DO_2 ;
CK_DOW: ;
MOV AX,OFFSET DOW_TAB ; Day of week abbreviation table
JMP DO_3 ;
;
; { Constant area reference.
;
TMPL_CONST: ;
CALL DTB ; Convert value to binary
OR DX,DX ; Constant number?
JNZ DO_CONST ;
CMP AL,'[' ; Indirect reference?
JE DO_INDIR ; Indirect constant reference
JMP TMPL_ERROR ; Incorrect constant reference
;
; We have {[nnn]}.
;
DO_INDIR: ;
CALL DTB ; Get input field reference
OR DX,DX ; Got a number?
JZ GO_TERR ; Yes
CMP AL,']' ; Closed properly?
JE INDIR_OK ;
GO_TERR: ;
JMP TMPL_ERROR ;
INDIR_OK: ;
DEC DX ;
SHL DX,1 ;
SHL DX,1 ;
CMP DX,EDIT_NUM ; Legal field reference?
JAE GO_TERR ; No
MOV SI,DX ;
MOV CX,EDIT_AREA[SI+2] ; End of area
MOV SI,EDIT_AREA[SI] ; Start of input
XOR DX,DX ;
INDIR_VAL: ;
LODSB ; Get next character
CMP AL,'0' ; If not a digit, skip
JB INDIR_SKIP ;
CMP AL,'9' ;
JA INDIR_SKIP ;
SUB AL,'0' ; Convert to binary
XCHG AL,DL ;
MUL C10 ;
ADD DX,AX ;
INDIR_SKIP: ;
INC SI ;
CMP SI,CX ;
JB INDIR_VAL ;
CALL GET_CHR ; Must have closing brace
JZ GO_TERR ;
;
; We have a constant reference.
;
DO_CONST: ;
CMP AL,'}' ; Closing brace?
JNE GO_TERR ;
DEC DX ;
SHL DX,1 ;
SHL DX,1 ;
CMP DX,CONST_NUM ; Legal constant reference?
JAE GO_TMPL ; No, ignore
MOV SI,DX ;
MOV DX,CONST_AREA[SI+2] ; End of constant area
MOV SI,CONST_AREA[SI] ; Start of constant
CONST_LP: ;
LODSB ;
CALL OUT_CHR ; Send next constant character
INC SI ;
CMP SI,DX ; Reached the end?
JB CONST_LP ; No
GO_TMPL: ;
JMP TMPL_LP ; Yes, continue processing template
;
; Processing complete.
;
WF_DONE: ;
CALL WR_OUT ; Write remaining buffered output
MOV CX,NUM_OUT ; Number of output files
XOR SI,SI ;
CLOSE_LP: ;
MOV BX,OUT_HNDL[SI] ; Close output file
MOV AH,CLOSE$ ;
INT DOS$ ;
INC SI ;
INC SI ;
LOOP CLOSE_LP ;
JMP SHORT EXIT_DOS ;
;
; Esc = Quit
;
ESC_SUB: ; Esc
MOV AX,OFFSET Q_MSG ;
MOV CX,L_Q ;
CALL STAT_MSG ; Display query "Really want to quit?"
Q_SOL: ;
XOR AH,AH ;
INT KYBD$ ; Read next character
AND AL,NOT 20H ; Make upper case
CMP AL,'Y' ; Really want to exit?
JE DO_QUIT ; Yes
CMP AL,'N' ; Want to keep going?
JNE Q_SOL ; No, resolicit
JMP EDIT_STATUS ; Keep on going
DO_QUIT: ;
CALL REST_VID ; Restore original screen
EXIT_DOS: ;
MOV AH,EXIT$ ; Return to DOS
XOR AL,AL ; Normal exit
INT DOS$ ;
;
; Commnon code for error message display and error exit to DOS.
;
ERROR_DSP: ;
MOV AH,WRFILE$ ; Display error message
MOV BX,ERROUT ;
INT DOS$ ;
MOV CX,2 ;
MOV DX,OFFSET CRLF ; Skip a line
MOV AH,WRFILE$ ;
INT DOS$ ;
MOV AH,EXIT$ ;
MOV AL,1 ; Error exit
INT DOS$ ;
;
;
; PROCEDURE FIND_AREA
;
; FIND_AREA finds the input area containing the current cursor position.
; If the position is not in an area, the next logical area start is
; returned.
;
; INPUT:
; SI = Current cursor location
;
; OUTPUT:
; BX = Pointer to area table entry
; CF = 1, Not in the area
; 0, In the area
;
FIND_AREA PROC ;
XOR BX,BX ; Search input table
FA_LP: ;
CMP BX,EDIT_NUM ; Still in table?
JA FA_FIRST ; No, go to home position
CMP SI,EDIT_AREA[BX] ; Within this area?
JB FA_NOT ; No
CMP SI,EDIT_AREA[BX+2] ;
JB FA_IN ; Yes
ADD BX,4 ; Try next area
JMP FA_LP ;
FA_FIRST: ;
XOR BX,BX ;
FA_NOT: ;
CLC ;
FA_IN: ;
CMC ; Set carry appropriately
RET ;
FIND_AREA ENDP ;
;
;
; PROCEDURE: DISP_MNU
;
; DISP_MNU displays a Nx40 menu on the screen.
;
; INPUT:
; AX = Menu location
; CX = Number of lines in menu
;
; OUTPUT:
; AX, CX contents destroyed.
;
DISP_MNU PROC ;
PUSH DX ;
PUSH DI ;
PUSH SI ;
XOR DI,DI ;
MOV DX,CX ; Number of lines
MOV SI,AX ; Start of menu
DM_LINE: ;
MOV CX,40 ;
DM_LP: ;
LODSW ;
CALL WRITE_SCREEN ; Display next character
LOOP DM_LP ;
ADD DI,WORD PTR SCR_COL ; New line
ADD DI,WORD PTR SCR_COL ;
SUB DI,80 ;
DEC DX ;
JNZ DM_LINE ;
POP SI ;
POP DI ;
POP DX ;
RET ;
DISP_MNU ENDP ;
;
;
; PROCEDURE STATUS
;
; Display status line.
;
; INPUT:
; DI = Current cursor position
; SI = Current file position
;
; OUTPUT:
; AX contents are destroyed.
;
STATUS PROC ;
PUSH CX ;
PUSH DX ;
PUSH DI ;
PUSH SI ;
;
; Convert row and column to ASCII and store in status line.
;
MOV AX,DI ;
SHR AX,1 ;
DIV SCR_COL ; Get column and row
MOV CL,AH ; Save column
XOR AH,AH ;
INC AL ;
MOV DI,OFFSET STAT_ROW ;
CALL BTD3 ; Convert and store row
MOV AL,CL ;
INC AL ;
XOR AH,AH ;
MOV DI,OFFSET STAT_COL ;
CALL BTD3 ;
;
; Convert file line number and put in status.
;
LEA AX,[SI-(OFFSET EDIT_LOC - OFFSET MENU_PSP)] ;
SHR AX,1 ;
CWD ;
DIV WORD PTR SCR_COL ; Get line number
INC AX ; Start at 1
MOV DI,OFFSET STAT_LIN ;
CALL BTD3 ; Convert high order
;
; Display status line.
;
MOV AH,STAT_ATTR ; Status display attribute
MOV SI,OFFSET STATUS_MSG ;
MOV DI,DISP_SIZE ;
MOV CX,WORD PTR SCR_COL ;
STAT_LP: ;
LODSB ;
CALL WRITE_SCREEN ;
LOOP STAT_LP ;
POP SI ;
POP DI ;
POP DX ;
POP CX ;
RET ;
STATUS ENDP ;
;
;
; PROCEDURE: STAT_MSG
;
; STAT_MSG displays a message in the status field.
;
; INPUT:
; AX = Start of message to display
; CX = Length of message to display
;
; OUTPUT:
; AX, CX contents destroyed.
;
STAT_MSG PROC ;
PUSH DI ;
PUSH SI ;
MOV SI,AX ; Location of message
MOV AX,CX ; Save count
MOV DI,OFFSET STAT_Q ;
REP MOVSB ; Copy query to status
MOV CX,Q_LNG ; Clear rest of message area
SUB CX,AX ;
MOV AL,' ' ;
REP STOSB ;
POP SI ;
POP DI ;
CALL STATUS ; Display message
RET ;
STAT_MSG ENDP ;
;
;
; PROCEDURE: STAT_CLR
;
; STAT_CLR clears the message area of the status line.
;
; INPUT:
; None
;
; OUTPUT:
; None
;
STAT_CLR PROC ;
PUSH AX ;
PUSH CX ;
PUSH DI ;
MOV CX,Q_LNG ;
MOV DI,OFFSET STAT_Q ;
MOV AL,' ' ;
REP STOSB ;
POP DI ;
POP CX ;
POP AX ;
RET ;
STAT_CLR ENDP ;
;
;
; PROCEDURE: GET_TIME
;
; GET_TIME gets the current date and time and edits the value to ASCII
; characters and places the values in the date and time variables.
;
; INPUT:
; None
;
; OUTPUT:
; MONTH, MON, DOW, DAY, CENTURY, YEAR, HOUR, MINUTE, SECOND updated.
;
GET_TIME PROC ;
;
; Save registers used.
;
PUSH AX ;
PUSH CX ;
PUSH DX ;
;
; Get date and convert to ASCII.
;
MOV AH,DATE$ ;
INT DOS$ ; Get current date
MOV AH,3 ; Convert DOW to an index
MUL AH ;
MOV DOW,AX ;
;
; Convert date to MM DD CC YY format.
; Compute month table index.
;
MOV AL,DH ; Month index
DEC AL ; Start index at 0
MOV AH,3 ;
MUL AH ;
MOV MON,AX ;
MOV AL,DH ; Do month
CALL BTD ; Convert to ASCII
MOV MONTH,AX ;
MOV AL,DL ; Day
CALL BTD ;
MOV DAY,AX ;
MOV AX,CX ; Year
MOV CL,100 ; Separate century
DIV CL ;
MOV CL,AH ; Save year
CALL BTD ;
MOV CENTURY,AX ; Century
MOV AL,CL ; Year
CALL BTD ;
MOV YEAR,AX ;
;
; Get time and convert to hh mm ss.
;
MOV AH,TIME$ ;
INT DOS$ ; Get current time
MOV AL,CH ; Hour
CALL BTD ;
MOV HOUR,AX ;
MOV AL,CL ; Minutes
CALL BTD ;
MOV MINUTE,AX ;
ADD DX,256-50 ; Round up seconds
MOV AL,DH ; Seconds
CALL BTD ;
MOV SECOND,AX ;
POP DX ;
POP CX ;
POP AX ;
RET ;
GET_TIME ENDP ;
;
;
; PROCEDURE BTD
;
; BTD converts a binary value from 00-99 to its decimal ASCII equivalent.
;
; INPUT:
; AL = Binary value
;
; OUTPUT:
; AX = ASCII value (low order in AH)
;
BTD PROC ;
XOR AH,AH ; Make a whole word
DIV C10 ; Separate digits
ADD AX,'00' ; Convert to ASCII
RET ;
BTD ENDP ;
;
;
; PROCEDURE BTD3
;
; BTD3 converts a binary value from 000-999 to its decimal ASCII equivalent
; and stores the result in a specified location.
;
; INPUT:
; AX = Value
; ES:DI = Location to save value
;
; OUTPUT:
; AX,DI contents destroyed.
;
BTD3 PROC ;
DIV C100 ; Isolate 100's digit
ADD AL,"0" ; Convert high order digit
STOSB ;
MOV AL,AH ;
CALL BTD ; Convert low order digits
STOSW ;
RET ;
BTD3 ENDP ;
;
;
; PROCEDURE DTB
;
; DTB converts a sequence of decimal characters to their binary equivalent.
; The resulting value must be <65536.
;
; INPUT:
; BX, CX, SI set up for GET_CHR
;
; OUTPUT:
; AL = Terminator character
; DX = Result value
;
DTB PROC ;
XOR DX,DX ; Zero accumulator
DTB_LP: ;
CALL GET_CHR ; Get next character
JZ DTB_END ; No more characters
CMP AL,'0' ; Decimal character?
JB DTB_END ; No, end of conversion
CMP AL,'9' ;
JA DTB_END ;
SUB AL,'0' ; Convert to binary
PUSH AX ;
MOV AX,DX ;
MUL WORD PTR C10 ; Multiply previous value
MOV DX,AX ;
POP AX ;
ADD DL,AL ;
ADC DH,0 ;
JMP DTB_LP ; Keep accumulating value
DTB_END: ;
RET ;
DTB ENDP ;
;
;
; PROCEDURE GET_CHR
;
; GET_CHR returns the next character of the current file. This may be either
; the SCREEN file or the TEMPLATE file. Once one file is read, it must be
; read through to the end without referencing any other file. The end of the
; file will be signalled and the file closed when no more characters remain
; in the file or the end-of-file sentinel character(26=1AH) is reached.
;
; INPUT:
; BX = File handle(SCREENFILE or TEMPLFILE)
; IN_CNT = Remaining characters in buffer
; IN_INDX = Pointer to next character
;
; OUTPUT:
; AL = Character
; IN_CNT, IN_INDX updated
; ZF = 1, end of file
;
GET_CHR PROC ;
;
; Check to see if any more characters remain
;
CMP IN_CNT,0 ; Any more in buffer
JZ READ_MORE ; No
;
; Get next character and return it.
;
XCHG SI,IN_INDX ;
LODSB ;
XCHG SI,IN_INDX ;
DEC IN_CNT ; Decrement character count
CMP AL,EOF_CHR ; Is it end of file?
JE FILE_DONE ; Yes
RET ;
;
; Read next buffer full of file.
;
READ_MORE: ;
PUSH AX ;
PUSH CX ;
PUSH DX ;
MOV AH,RDFILE$ ;
MOV CX,L_INB ; Read all that buffer will hold
MOV DX,OFFSET CHR_LOC ;
MOV IN_INDX,DX ;
INT DOS$ ; Read file
MOV IN_CNT,AX ; Save amount read
POP DX ;
POP CX ;
POP AX ;
JC SCRN_ERROR ; Error reading file
CMP IN_CNT,0 ; Any data read?
JNZ GET_CHR ; Read is OK, so return the character
FILE_DONE: ;
PUSHF ; Preserve carry flag
PUSH AX ;
MOV AH,CLOSE$ ; Close the file
INT DOS$ ;
POP AX ;
POPF ;
MOV IN_CNT,1 ; Continue to signal EOF
MOV IN_INDX,OFFSET CHR_LOC ;
MOV CHR_LOC,EOF_CHR ;
XOR AL,AL ; Indicate end of file
RET ;
;
; Error reading screen file.
;
SCRN_ERROR: ;
CMP BX,SCREENFILE ; Screen file?
JNE TMPL_FAIL ; No, template file
MOV DX,OFFSET SCRN_ERR ;
MOV CX,L_SERR ;
JMP ERROR_DSP ;
;
; Error reading template file.
;
TMPL_FAIL: ;
MOV CX,L_TMPL ;
MOV DX,OFFSET TMPL_ERR ;
JMP ERROR_DSP ;
GET_CHR ENDP ;
;
;
; PROCEDURE OUT_CHR
;
; OUT_CHR sends one character to the output file.
;
; INPUT:
; AL = Character to send
;
; OUTPUT:
; None
;
; PROCEDURE WR_OUT
;
; WR_OUT writes any remaining buffered output to the output file.
;
; INPUT:
; None
;
; OUTPUT:
; None
;
OUT_CHR PROC ;
;
; Save registers used.
;
PUSH BX ;
;
; Add character to buffer. If buffer full, write to file.
;
MOV BX,OUT_INDX ;
MOV OUT_BUF[BX],AL ;
INC BX ;
MOV OUT_INDX,BX ;
POP BX ;
CMP BX,L_OUTB ; Buffer full?
JAE WR_OUT ; Yes
RET ;
;
; Write data to out file.
;
WR_OUT: ;
PUSH AX ;
PUSH BX ;
PUSH CX ;
PUSH DX ;
MOV CX,OUT_INDX ; Amount to write
JCXZ NO_OUT ;
MOV AH,WRFILE$ ;
MOV BX,OUTFILE ;
MOV DX,OFFSET OUT_BUF ;
INT DOS$ ; Write file
JC OUT_ERR ;
NO_OUT: ;
POP DX ;
POP CX ;
POP BX ;
POP AX ;
RET ;
OUT_ERR: ;
MOV CX,L_OUT ;
MOV DX,OFFSET OUT_MSG ;
JMP ERROR_DSP ;
OUT_CHR ENDP ;
;
;
; PROCEDURE DISP_SCREEN
;
; DISP_SCREEN redisplays the screen.
; SCR_LIN*SCR_COL characters are displayed.
;
; If the show fields flag is set, new field definitions are indicated by
; blinking []'s (║ if a single position) and constant area definitions
; are indicated by blinking {}'s (╬ if a single position).
;
; INPUT:
; DI = Screen cursor position
; SI = Edit buffer cursor position
;
; OUTPUT:
; None
;
DISP_SCREEN PROC ;
;
; Save registers used.
; Save current cursor position.
;
PUSH AX ;
PUSH DI ;
PUSH SI ;
;
; Display characters until end of screen or buffer.
;
SUB SI,DI ; Start of screen in edit buffer
XOR DI,DI ;
DISP_LP: ;
MOV AL," " ; Default space
MOV AH,SCR_ATTR ; Empty attribute
CMP SI,EDIT_LAST ; End of characters?
JA NO_CHR ; Yes
LODSW ; Get next char
NO_CHR: ;
CALL WRITE_SCREEN ;
CMP DI,DISP_SIZE ; End of screen
JB DISP_LP ; No
;
; If the show fields flag is set, insert field indicator characters.
;
CMP SHOW,0 ; Showing definitions?
JZ NO_SHOW ; No
PUSH BX ;
XOR BX,BX ;
SUB SI,DI ; Back to start of screen
SHDF_LP: ; Do all input and constant definitions
MOV AL,'[' ; Input definitions
MOV DI,DEF_AREA[BX] ;
CALL SHOW_IT ; Start
MOV AL,']' ;
MOV DI,DEF_AREA[BX+2] ;
DEC DI ;
DEC DI ;
CMP DI,DEF_AREA[BX] ; Start and end the same?
JNE NOT_DBL1 ;
MOV AL,'║' ;
NOT_DBL1: ;
CALL SHOW_IT ; End
MOV AL,'{' ; Constant definitions
MOV DI,CONST_AREA[BX] ;
CALL SHOW_IT ; Start
MOV AL,'}' ;
MOV DI,CONST_AREA[BX+2] ;
DEC DI ;
DEC DI ;
CMP DI,CONST_AREA[BX] ; Start and end the same?
JNE NOT_DBL2 ;
MOV AL,'╬' ;
NOT_DBL2: ;
CALL SHOW_IT ; End
ADD BX,4 ;
CMP BX,EDIT_FLD*4 ;
JB SHDF_LP ;
NO_CNDF: ;
POP BX ;
NO_SHOW: ;
POP SI ;
POP DI ;
POP AX ;
RET ;
;
; Check if on this screen and display if so.
;
SHOW_IT: ;
CMP DI,0 ; Definition present?
JZ NOT_SH ;
MOV AH,[DI+1] ; Get attribute
CMP DI,SI ; On this screen?
JB NOT_SH ; No
SUB DI,SI ; Offset to this one
CMP DI,DISP_SIZE ; On screen?
JAE NOT_SH ; No
OR AH,80H ; Set blink
CALL WRITE_SCREEN ; Display it
NOT_SH: ;
RET ;
DISP_SCREEN ENDP ;
;
;
; PROCEDURE REST_VID
;
; REST_VID restores the screen as it was prior to doing the menu editing.
;
; INPUT:
; None
;
; OUTPUT:
; None
;
REST_VID PROC ;
;
; Save registers used.
;
PUSH AX ;
PUSH BX ;
PUSH DX ;
PUSH DI ;
PUSH SI ;
;
; Restore video modes and screen.
;
MOV SI,DISP_LOC ;
CMP SI,0 ; Did we save the screen?
JZ NO_REST ; No
MOV AX,WORD PTR SCR_COL ;
SHL AX,1 ;
ADD DISP_SIZE,AX ; Include the last line
MOV EDIT_LAST,-1 ; Make sure area considered in display
XOR DI,DI ; At top of screen
CALL DISP_SCREEN ; Redisplay the screen
NO_REST: ;
MOV BH,SAVEPAGE ;
MOV AL,BH ;
MOV AH,PAGE$ ;
INT VIDEO$ ;
MOV DX,SAVECRS ;
MOV AH,CRS$ ;
INT VIDEO$ ; Restore cursor position
POP SI ;
POP DI ;
POP DX ;
POP BX ;
POP AX ;
RET ;
REST_VID ENDP ;
;
;
; PROCEDURE: WRITE_SCREEN
;
; WRITE_SCREEN writes a character directly to the video refresh memory.
;
; INPUT:
; AX = Character and attribute to write
; DI = Location at which to write character
;
; OUTPUT:
; DI = DI + 2
;
WRITE_SCREEN PROC ;
;
; Compute video memory offset.
;
PUSH BX ;
PUSH DX ;
PUSH ES ;
MOV ES,VIDEO_SEG ; Screen segment
ASSUME ES:NOTHING ;
CMP FAST,0 ; Fast screen update?
JNZ FAST_WRITE ;
MOV BX,AX ;
MOV DX,STATUS_REG ; Retrieve status register.
HORZ_RET: ;
IN AL,DX ; Get status from adaptor
TEST AL,1 ; Is it low?
JNZ HORZ_RET ; If not, wait until it is.
CLI ; No more interrupts.
WAIT_RET: ;
IN AL,DX ; Get status.
TEST AL,1 ; Is it high?
JZ WAIT_RET ; If no, wait until it is.
MOV AX,BX ; Retrieve character; now it's OK
FAST_WRITE: ; Move the following code up
STOSW ; to write to screen buffer.
STI ; Interrupts back on.
POP ES ;
ASSUME ES:CODE ;
POP DX ;
POP BX ;
RET ;
WRITE_SCREEN ENDP ;
;
;
; PROCEDURE: TRIM
;
; TRIM determines the last non-blank character in an area on the screen.
; Any location that contains the start or end of a defined input field is
; also considered to be non-blank.
; TRIM also considers a change in attribute value the equivalent of a non-blank.
;
; INPUT:
; DX = Start of area
; DI = End of area+2(i.e., location after end)
; AH = Attribute of preceding location
;
; OUTPUT:
; DI = Last non-blank(or attribute change)+2
; DI = DX, entire area blank
;
TRIM PROC ;
PUSH AX ;
PUSH BX ;
PUSH CX ;
MOV AL,[DI-1] ; Last attribute
TRIM_IT: ;
CMP DX,DI ; At start of area?
JE TRIM_DONE ; Yes, nothing to do
CMP BYTE PTR [DI-2],' ' ; Blank?
JNE TRIM_DONE ; No, found end
LEA CX,[DI-2] ;
XOR BX,BX ;
TRIM_LP: ;
CMP BX,DEF_NUM ; Any more input fields?
JAE TRIM_DF ; No
CMP CX,DEF_AREA[BX] ; Start of defined field?
JE TRIM_DONE ; Yes, in next position
CMP DI,DEF_AREA[BX+2] ; End of defined field?
JE TRIM_DONE ; Yes
ADD BX,4 ; Next definition
JMP TRIM_LP ;
TRIM_DF: ;
CMP CX,DX ; At first position?
JA TRIM_CK ; No
CMP AH,[DI-1] ; Is attribute different than entry?
JNE TRIM_DONE ; Yes
JMP SHORT TRIM_NA ;
TRIM_CK: ;
CMP AL,[DI-3] ; Does attribute change?
JNE TRIM_DONE ; Yes
TRIM_NA: ;
DEC DI ; Back up one
DEC DI ;
JMP TRIM_IT ;
TRIM_DONE: ;
POP CX ;
POP BX ;
POP AX ;
RET ;
TRIM ENDP ;
;
;
; PROCEDURE: TBL_SRCH
;
; TBL_SRCH searches a list of characters and returns the index*2 of any match
; or 0 for no match. The result value may be used to index a corresponding
; table of word size values with the 0th entry being the no-match entry.
;
; INPUT:
; AL = Character to be matched
; CX = Length of table to search
; SI = Location of table to search
;
; OUTPUT:
; SI = 0 if no match or index*2 of match
; CX contents are destroyed
;
TBL_SRCH PROC ;
PUSH DI ;
MOV DI,SI ; Table base
REPNE SCASB ; Search the table
JE TBL_FND ; If we found a match
MOV DI,SI ; So we generate a 0 result
TBL_FND: ;
SUB SI,DI ; Form index
NEG SI ;
SHL SI,1 ; Double for word index
POP DI ;
RET ;
TBL_SRCH ENDP ;
;
;
; PROCEDURE: WTBL_SRCH
;
; WTBL_SRCH searches a list of words and returns the index of any match
; or 0 for no match. The result value may be used to index a corresponding
; table of word size values with the 0th entry being the no-match entry.
;
; INPUT:
; AX = Word to be matched
; CX = Length of table to search
; SI = Location of table to search
;
; OUTPUT:
; SI = 0 if no match or index of match
; CX contents are destroyed
;
WTBL_SRCH PROC ;
PUSH DI ;
MOV DI,SI ; Table base
REPNE SCASW ; Search the table
JE WTBL_FND ; If we found a match
MOV DI,SI ; So we generate a 0 result
WTBL_FND: ;
SUB SI,DI ; Form index
NEG SI ;
POP DI ;
RET ;
WTBL_SRCH ENDP ;
;
;
; PROCEDURE: FIELD_GEN
;
; FIELD_GEN is called when a screen file has been edited and is being output
; to check for input and constant fields and insert the bracketing characters
; as appropriate.
;
; INPUT:
; AL = '[' or ']' for start or end check
; DI = File index to check
;
; OUTPUT:
; None
;
FIELD_GEN PROC ;
PUSH BX ;
;
; Loop through field definitions.
;
XOR BX,BX ; Check for start of input
CMP AL,'[' ; Field start?
JE FG_LP ; Yes
INC BX ; Use end of field
INC BX ;
FG_LP: ;
CMP BX,DEF_NUM ; Any more input fields?
JAE NO_DEF ; No
CMP DI,DEF_AREA[BX] ; Start of field?
JNE NO_DEF ; Yes
CALL OUT_CHR ; Put start of input
NO_DEF: ;
CMP BX,CONST_NUM ; Any more constant fields?
JAE NO_CONST ; No
CMP DI,CONST_AREA[BX] ; Start of constant?
JNE NO_CONST ;
OR AL,20H ; Put start of constant
CALL OUT_CHR ;
AND AL,NOT 20H ;
NO_CONST: ;
ADD BX,4 ;
CMP BX,EDIT_FLD*4 ; Processed all possible fields?
JB FG_LP ;
POP BX ;
RET ;
FIELD_GEN ENDP ;
;
; Location of reusable space.
;
CHR_LOC LABEL BYTE ; Input buffer
OUT_BUF EQU CHR_LOC+L_INB ; Output I/O buffer
;
; Initialization data.
;
ERROR_MSG LABEL BYTE ;
DB "MENU [/D/E/N] screen template out" ;
L_ERROR EQU $-ERROR_MSG ;
OPT_CHR LABEL BYTE ;
DB 'NDE' ; Option letters
L_OPT EQU $-OPT_CHR ;
OPT_VECT LABEL WORD ;
DW BAD_OPT ;
DW N_OPT ;
DW D_OPT ;
DW E_OPT ;
;
;
; INIT performs video and file initialization for MENU. It is placed at the
; end of the program area so that its space may be reused.
;
INIT: ;
;
; Find input file name and open it.
;
MOV SI,OFFSET P_CNT ;
LODSB ; Get count
XOR AH,AH ;
MOV CX,AX ;
XOR AL,AL ; Open for input only
XOR BX,BX ; Default to standard input or none
CALL OPEN_FILE ; Parse file name and open file
JC ERROR_FILE ; Error getting file
MOV SCREENFILE,AX ; Save handle
JMP GET_TMPL ;
;
; File does not exist.
;
ERROR_FILE: ;
MOV CX,L_ERROR ;
MOV DX,OFFSET ERROR_MSG ;
JMP ERROR_DSP ;
;
; Find template file name.
;
GET_TMPL: ;
XOR BX,BX ;
XOR AL,AL ;
CALL OPEN_FILE ; Get template file
JC ERROR_FILE ;
MOV TEMPLFILE,AX ; Template handle
;
; Get output file name.
;
MOV BX,STDOUT ; Default to standard output
MOV AL,1 ; Open file for writing
CALL OPEN_FILE ;
JC ERROR_FILE ;
MOV OUTFILE,AX ; Output file handle
;
; See if multiple output files specified.
;
MOV DI,OFFSET OUT_HNDL ;
OUT_LP: ;
STOSW ; Save handle in output table
INC NUM_OUT ; Increment count of output files
OUT_SKP: ;
JCXZ CHECK_VOID ; No more files, check void
MOV AL,1 ; Create the file
CALL OPEN_FILE ;
JC ERROR_FILE ;
CMP AX,STDOUT ; Any file name there?
JNE OUT_LP ; Yes
JMP OUT_SKP ; No, skip saving handle
CHECK_VOID: ;
CMP DOPT,L_DOPT ; Only /D is legal
JE CHECK_VID ;
CMP SCREENFILE,0 ; Any parameters?
JE ERROR_FILE ; No, error
;
; Determine current video modes and save them.
;
CHECK_VID: ;
MOV AX,BIOS_DATA ; Point to the ROM BIOS data area
MOV DS,AX ; and get base address of active
ASSUME DS:BIOS_DATA ;
MOV AX,ADDR_6845 ; display card.
PUSH CS ; Restore DS
POP DS ;
ASSUME DS:CODE ;
ADD AX,6 ; Add six to get status register
MOV STATUS_REG,AX ; Store status register.
CMP AX,3BAH ; Status port of MONO card is 3BAH.
JE MONO ; If that's what we got, it's MONO
MOV VIDEO_SEG,COLOR_SEG ; else COLOR so use that seg
MOV AH,ALTSEL$ ; Try to select the EGA/VGA
MOV BL,10H ; Ask EGA/VGA for status
INT VIDEO$ ;
CMP BL,10H ; EGA/VGA present?
JE CGA ; No, assume old CGA
MOV AX,BIOS_DATA ; There is an EGA/VGA. Check if it is
MOV DS,AX ; the one we are using.
ASSUME DS:BIOS_DATA ;
MOV AL,EGA_INFO ; Get EGA/VGA status byte
PUSH CS ;
POP DS ;
ASSUME DS:CODE ;
TEST AL,EGA_MASK ; Is EGA/VGA active?
JNZ CGA ; No, do CGA initialization only
;
; Since it is an EGA/VGA, there may be other than 25 lines per screen. Get the
; actual number and change MENU to use it.
;
XOR BH,BH ;
MOV AX,EGASTAT$*256+48 ;
INT VIDEO$ ; EGA/VGA get status
PUSH CS ;
POP ES ; Reset ES changed by VIDEO$
INC DL ; Number of lines
MOV SCR_LIN,DL ;
;
; For monochrome and EGA/VGA controllers, we do not need to wait for horizontal
; retrace before putting a character on the display.
;
MONO: ; MDA or EGA/VGA
MOV FAST,1 ; Set fast video flag
CGA: ;
MOV AH,VIDSTAT$ ; Get video state
INT VIDEO$ ;
MOV SCR_COL,AH ; Save number of columns
MOV SAVEPAGE,BH ; Save current video page
CMP AL,3 ; Check for legal video modes
JBE VID_OK ; OK
CMP AL,7 ;
JE VID_OK ;
MOV AH,SMODE$ ;
MOV AL,3 ; Switch to standard text mode
INT VIDEO$ ;
MOV DISP_LOC,0 ; Don't try to save cleared screen
JMP CHECK_VID ; Get state again
VID_OK: ;
MOV AH,RDCRS$ ;
INT VIDEO$ ; Save cursor position
MOV SAVECRS,DX ;
MOV AL,SCR_LIN ; Compute display area size
DEC AL ;
MUL SCR_COL ;
MOV DISP_SIZE,AX ;
SHL DISP_SIZE,1 ; Room for attributes
ADD AX,WORD PTR SCR_COL ;
INC AX ; Don't run right up to end
SHL AX,1 ; Words
NEG AX ;
CMP DISP_LOC,0 ; Are we saving the screen?
JNZ SV_SCRN ; Yes
XOR AX,AX ; No size required
SV_SCRN: ;
ADD AX,SP ; Subtract from size of program
SUB AX,100H ; Leave room for stack
CMP DISP_LOC,0 ; Save screen?
JZ NO_SVSCR ; No
MOV DISP_LOC,AX ; Location of screen save area
NO_SVSCR: ;
;
; Initialize edit area to contain blanks.
;
MOV DI,OFFSET EDIT_LOC ;
SUB AX,DI ; Length of file area
SUB AX,WORD PTR SCR_COL ; Leave pad for last line spaces
SHR AX,1 ;
CWD ;
DIV WORD PTR SCR_COL ; Make multiple of line length
MUL WORD PTR SCR_COL ;
SHL AX,1 ;
MOV CX,AX ;
ADD AX,OFFSET EDIT_LOC-2 ;
MOV EDIT_LAST,AX ;
SHR CX,1 ; Number of words
MOV AL," " ;
MOV AH,SCR_ATTR ;
REP STOSW ;
;
; Save current screen.
;
CMP DISP_LOC,0 ; Are we saving the screen?
JZ NO_SCRN ; No
XOR AL,AL ;
MOV AH,PAGE$ ; Force page 0
INT VIDEO$ ;
MOV DI,DISP_LOC ;
MOV CX,DISP_SIZE ;
SHR CX,1 ;
ADD CX,WORD PTR SCR_COL ; Full screen size
XOR SI,SI ; Start at top of screen
SAV_LP: ;
CALL READ_SCREEN ;
STOSW ; Save
LOOP SAV_LP ;
NO_SCRN: ;
JMP BEGIN ; Start processing edit file
;
;
; PROCEDURE: READ_SCREEN
;
; READ_SCREEN writes a character directly from the video refresh memory.
;
; INPUT:
; SI = Location in video refresh memory to read
;
; OUTPUT:
; AX = Character and attribute
; SI = SI + 2
; DX contents are destroyed.
;
READ_SCREEN PROC ;
PUSH ES ;
MOV ES,VIDEO_SEG ; Screen segment
ASSUME ES:NOTHING ;
CMP FAST,0 ; Fast screen?
JNZ FAST_READ ; Yes
;
; Wait for horizontal retrace before reading.
;
MOV DX,STATUS_REG ; Retrieve status register.
HORZ_RET2: ;
IN AL,DX ; Get status from adaptor
TEST AL,1 ; Is it low?
JNZ HORZ_RET2 ; If not, wait until it is.
CLI ; No more interrupts.
WAIT_RET2: ;
IN AL,DX ; Get status.
TEST AL,1 ; Is it high?
JZ WAIT_RET2 ; If no, wait until it is.
FAST_READ: ;
LODS WORD PTR ES:[SI] ; to read to screen buffer.
STI ; Interrupts back on.
POP ES ;
ASSUME ES:CODE ;
RET ;
READ_SCREEN ENDP ;
;
;
; PROCEDURE OPEN_FILE
;
; OPEN_FILE parses the next file name in the parameter area and opens
; the file. If the file is opened for output only, the file is created.
;
; INPUT:
; AL = Open mode to use (0=read, 1=create, 2=update)
; BX = File handle to use if field missing
; CX = Remaining input character count
; SI = Next input character
;
; OUTPUT:
; AX = Return from OPEN (handle or error status)
; CF = 1, error
; CX,SI Updated
;
OPEN_FILE PROC ;
;
; Save registers used.
;
PUSH DX ;
PUSH AX ;
;
; Find start of file name by skipping any white space characters.
;
FIND_AGAIN: ;
JCXZ MIS_FIL ;
FIND_STRT: ;
LODSB ; Get next character
CMP AL," " ; Skip leading blanks/tabs
JE SKIP_SEP ;
CMP AL,TAB_CHR ;
JNE STRT_FND ; Found start of filename
SKIP_SEP: ;
LOOP FIND_STRT ;
MIS_FIL: ; Use default file handle
POP AX ;
POP DX ;
MOV AX,BX ;
CLC ;
RET ;
;
; Found start of file name. Now find end.
;
STRT_FND: ;
CMP AL,'/' ; Option?
JE DO_OPT ; Yes
LEA DX,[SI-1] ; Start of file name
JMP SHORT CHK_FIL ;
FIL_LP: ;
LODSB ;
CHK_FIL: ;
CMP AL," " ;
JE END_FIL ; Found end of it
CMP AL,"," ;
JE END_FIL ;
CMP AL,TAB_CHR ;
JE END_FIL ;
CMP AL,CR_CHR ;
JE END_FIL ;
LOOP FIL_LP ; Continue scanning
INC SI ;
INC CX ;
;
; Found end of file name. Open file.
;
END_FIL: ;
DEC CX ;
LEA AX,[SI-1] ; Ending location
CMP AX,DX ; No file?
JE MIS_FIL ; Yes, use default
MOV BYTE PTR [SI-1],0 ; Make ASCIIZ
POP AX ; Open type
CMP AL,1 ; Open for output only?
JE CRE_FILE ; Yes
MOV AH,OPEN$ ;
INT DOS$ ;
POP DX ;
RET ;
;
; Create a new file.
;
CRE_FILE: ;
PUSH CX ;
XOR CX,CX ; Normal file type
MOV AH,CREATE$ ; Create the file
INT DOS$ ;
POP CX ;
POP DX ;
RET ;
;
; Check for /N = No_save_screen.
; or /D = Display only (Only ANSI sequences processed.)
; or /E = Edit screen file
;
DO_OPT: ;
DEC CX ;
JCXZ MIS_FIL ;
LODSB ; Get option letter
DEC CX ;
AND AL,NOT 20H ; Force to upper case
PUSH CX ;
PUSH SI ;
MOV CX,L_OPT ;
MOV SI,OFFSET OPT_CHR ;
CALL TBL_SRCH ;
JMP OPT_VECT[SI] ; Switch on option
N_OPT: ;
MOV DISP_LOC,0 ; No screen save required
OK_OPT: ;
POP SI ;
POP CX ;
JMP FIND_AGAIN ; Continue scanning
D_OPT: ;
MOV DOPT,L_DOPT ; Display only, do not process
JMP OK_OPT ; control characters
E_OPT: ;
MOV EOPT,L_EDIT ; Set edit flag
JMP OK_OPT ; Force display mode
BAD_OPT: ;
POP SI ;
POP CX ;
POP AX ;
POP DX ;
STC ; Error signal
RET ;
OPEN_FILE ENDP ;
MENU ENDP ;
EDIT_LOC EQU OUT_BUF+L_OUTB ; Buffer for editing
CODE ENDS ;
END MENU ;